package goods

import (
	. "awesomeProject/goods-web/api"
	"awesomeProject/goods-web/forms"
	"awesomeProject/goods-web/global"
	"awesomeProject/goods-web/proto"
	"context"
	"fmt"
	sentinel "github.com/alibaba/sentinel-golang/api"
	"github.com/alibaba/sentinel-golang/core/base"
	"go.uber.org/zap"
	"strconv"

	"github.com/gin-gonic/gin"
	"net/http"
)

// 全局变量
var (
// 注意用户服务的端口！！！我们写入了配置文件中
// 不能把端口设置为全局变量，因为还没有初始化
)

func List(ctx *gin.Context) {

	// web端接收前端请求，并组织request
	request := proto.GoodsFilterRequest{}
	// 通过GET方法，然后通过url选取
	priceMin := ctx.DefaultQuery("pmin", "0") // pmin为前后端约定字段---最小值
	priceMinInt, _ := strconv.Atoi(priceMin)
	request.PriceMin = int32(priceMinInt)

	priceMax := ctx.DefaultQuery("pmax", "0") // pmax为前后端约定字段---最大值
	priceMaxInt, _ := strconv.Atoi(priceMax)
	request.PriceMax = int32(priceMaxInt)

	isHot := ctx.DefaultQuery("ih", "0") // ih为前后端约定字段---热门商品为1，非热门为0
	if isHot == "1" {
		request.IsHot = true
	}

	isTab := ctx.DefaultQuery("it", "0") // it为前后端约定字段---为标签栏1，非标签栏为0
	if isTab == "1" {
		request.IsTab = true
	}

	categoryId := ctx.DefaultQuery("c", "0") // c为前后端约定字段---品类id
	categoryIdInt, _ := strconv.Atoi(categoryId)
	request.TopCategory = int32(categoryIdInt)

	pages := ctx.DefaultQuery("p", "0") // p为前后端约定字段---分页
	pagesInt, _ := strconv.Atoi(pages)
	request.Pages = int32(pagesInt)

	pageNum := ctx.DefaultQuery("pnum", "0") // pnum为前后端约定字段---页码
	pageNumInt, _ := strconv.Atoi(pageNum)
	request.PagePerNums = int32(pageNumInt)

	keywords := ctx.DefaultQuery("q", "") // q为查询关键字
	request.KeyWords = keywords

	brandId := ctx.DefaultQuery("b", "0") // b为品牌
	brandIdInt, _ := strconv.Atoi(brandId)
	request.Brand = int32(brandIdInt)

	// 维护链路追踪的span和parentSpan
	//parentSpan, _ := ctx.Get("parentSpan")
	// 传入父级Span，但是我们的后端，是收不到我们当前的span的
	//opentracing.ContextWithSpan(context.Background(), parentSpan.(opentracing.Span))

	entry, blockErr := sentinel.Entry("goods-list", sentinel.WithTrafficType(base.Inbound))
	if blockErr != nil { // 限流了
		zap.S().Fatal("Block error: ", blockErr)
		ctx.JSON(http.StatusTooManyRequests, gin.H{
			"msg": "当前请求过多，请稍后重试",
		})
		return
	}

	rsp, err := global.GoodsSrvClient.GoodsList(context.WithValue(context.Background(), "ginContext", ctx), &request) // 向服务端请求商品的service的后端服务
	if err != nil {
		zap.S().Errorf("查询商品列表失败", err.Error())
		HandleValidateError(err, ctx)
		return
	}
	// 限流结束
	entry.Exit()

	// 读取rsp中的数据，返回给前端
	reMap := map[string]interface{}{
		"total": rsp.Total,
	}
	// 手动按照前端的约定，维护rsp.data
	goodsList := make([]interface{}, 0)
	for _, good := range rsp.Data {

		goodsList = append(goodsList, map[string]interface{}{
			"id":          good.Id,
			"name":        good.Name,
			"goods_brief": good.GoodsBrief,
			"desc":        good.GoodsDesc,
			"ship_free":   good.ShipFree,
			"images":      good.Images,
			"desc_images": good.DescImages,
			"front_image": good.GoodsFrontImage,
			"shop_price":  good.ShopPrice,
			"category": map[string]interface{}{
				"id":   good.Category.Id,
				"name": good.Category.Name,
			},
			"brand": map[string]interface{}{
				"id":   good.Brand.Id,
				"name": good.Brand.Name,
				"logo": good.Brand.Logo,
			},
			"is_hot":  good.IsHot,
			"is_new":  good.IsNew,
			"on_sale": good.OnSale,
		})
	}
	reMap["list"] = goodsList

	ctx.JSON(http.StatusOK, reMap)

}

func New(ctx *gin.Context) {

	goodsForm := forms.GoodsForm{}
	if err := ctx.ShouldBind(&goodsForm); err != nil {
		HandleValidateError(err, ctx)
		return
	}

	goodsClient := global.GoodsSrvClient
	rsp, err := goodsClient.CreateGoods(ctx, &proto.CreateGoodsInfo{
		Name:            goodsForm.Name,
		GoodsSn:         goodsForm.GoodsSn,
		Stocks:          goodsForm.Stocks,
		MarketPrice:     goodsForm.MarketPrice,
		ShopPrice:       goodsForm.ShopPrice,
		GoodsBrief:      goodsForm.GoodsBrief,
		ShipFree:        *goodsForm.ShipFree,
		Images:          goodsForm.Images,
		DescImages:      goodsForm.DescImages,
		GoodsFrontImage: goodsForm.FrontImage,
		CategoryId:      goodsForm.CategoryId,
		BrandId:         goodsForm.Brand,
	})
	if err != nil {
		HandleGrpcErrorToHttp(err, ctx)
		return
	}

	// 库存的设置我们这里不进行，因为需要处理分布式事务
	ctx.JSON(http.StatusOK, rsp)
}

func Detail(ctx *gin.Context) {

	idStr := ctx.Param("id")
	id, err := strconv.ParseInt(idStr, 10, 32)
	if err != nil {
		HandleGrpcErrorToHttp(err, ctx)
		return
	}

	rsp, err := global.GoodsSrvClient.GetGoodsDetail(context.Background(), &proto.GoodInfoRequest{
		Id: int32(id),
	})
	if err != nil {
		HandleGrpcErrorToHttp(err, ctx)
		return
	}

	// 商品信息的库存是通过库存子服务获取的
	rspMap := map[string]interface{}{
		"id":          rsp.Id,
		"name":        rsp.Name,
		"goods_brief": rsp.GoodsBrief,
		"desc":        rsp.GoodsDesc,
		"ship_free":   rsp.ShipFree,
		"images":      rsp.Images,
		"desc_images": rsp.DescImages,
		"front_image": rsp.GoodsFrontImage,
		"shop_price":  rsp.ShopPrice,
		"category": map[string]interface{}{
			"id":   rsp.Category.Id,
			"name": rsp.Category.Name,
		},
		"brand": map[string]interface{}{
			"id":   rsp.Brand.Id,
			"name": rsp.Brand.Name,
			"logo": rsp.Brand.Logo,
		},
		"is_hot":  rsp.IsHot,
		"is_new":  rsp.IsNew,
		"on_sale": rsp.OnSale,
	}
	ctx.JSON(http.StatusOK, rspMap)
}

func Delete(ctx *gin.Context) {
	idStr := ctx.Param("id")
	id, err := strconv.ParseInt(idStr, 10, 32)
	if err != nil {
		HandleGrpcErrorToHttp(err, ctx)
		return
	}

	_, err = global.GoodsSrvClient.DeleteGoods(context.Background(), &proto.DeleteGoodsInfo{
		Id: int32(id),
	})
	if err != nil {
		HandleGrpcErrorToHttp(err, ctx)
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"msg": "删除成功",
	})
	return
}

func Stocks(ctx *gin.Context) {
	idStr := ctx.Param("id")
	id, err := strconv.ParseInt(idStr, 10, 32)
	if err != nil {
		HandleGrpcErrorToHttp(err, ctx)
		return
	}

	// todo 获取商品库存
	fmt.Println(id)
}

func UpdateStatus(ctx *gin.Context) {
	// 先获取更新状态的商品ID
	idStr := ctx.Param("id")
	id, err := strconv.ParseInt(idStr, 10, 32)
	if err != nil {
		HandleGrpcErrorToHttp(err, ctx)
		return
	}
	fmt.Println(id)
	// 从表单读取状态
	goodStatusFrom := forms.GoodsStatusForm{}
	if err := ctx.ShouldBind(&goodStatusFrom); err != nil {
		HandleValidateError(err, ctx)
		return
	}

	_, err = global.GoodsSrvClient.UpdateGoods(context.Background(), &proto.CreateGoodsInfo{
		Id:     int32(id),
		IsNew:  *goodStatusFrom.IsNew,
		IsHot:  *goodStatusFrom.IsHot,
		OnSale: *goodStatusFrom.OnSale,
	})
	if err != nil {
		HandleGrpcErrorToHttp(err, ctx)
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"msg": "修改成功",
	})
	return
}

// 这几个update接口测试不了

func Update(ctx *gin.Context) {
	goodsForm := forms.GoodsForm{}
	if err := ctx.ShouldBindJSON(&goodsForm); err != nil {
		HandleValidateError(err, ctx)
		return
	}

	idStr := ctx.Param("id")
	id, err := strconv.ParseInt(idStr, 10, 32)
	if _, err = global.GoodsSrvClient.UpdateGoods(context.Background(), &proto.CreateGoodsInfo{
		Id:              int32(id),
		Name:            goodsForm.Name,
		GoodsSn:         goodsForm.GoodsSn,
		Stocks:          goodsForm.Stocks,
		MarketPrice:     goodsForm.MarketPrice,
		ShopPrice:       goodsForm.ShopPrice,
		GoodsBrief:      goodsForm.GoodsBrief,
		ShipFree:        *goodsForm.ShipFree,
		Images:          goodsForm.Images,
		DescImages:      goodsForm.DescImages,
		GoodsFrontImage: goodsForm.FrontImage,
		CategoryId:      goodsForm.CategoryId,
		BrandId:         goodsForm.Brand,
	}); err != nil {
		HandleGrpcErrorToHttp(err, ctx)
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"msg": "更新成功",
	})

}
